package net.tv90.bfmccore.game.impl.cq;

import lk.vexview.api.VexViewAPI;
import lk.vexview.gui.components.VexImage;
import lk.vexview.hud.VexImageShow;
import lk.vexview.hud.VexTextShow;
import net.tv90.bfmccore.event.FlagCapturedEvent;
import net.tv90.bfmccore.event.FlagNeutralizedEvent;
import net.tv90.bfmccore.game.GameManager;
import net.tv90.bfmccore.game.GameUtils;
import net.tv90.bfmccore.game.view.GameModelViewHandler;
import net.tv90.bfmccore.game.impl.EnumSpawnPolicy;
import net.tv90.bfmccore.helper.FactionHelper;
import net.tv90.bfmccore.util.Cooldown;
import net.tv90.bfmccore.util.area.Area;
import net.tv90.bfmccore.util.vector.Vector3i;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static net.tv90.bfmccore.game.GameBase.firstFactionList;
import static net.tv90.bfmccore.game.GameBase.secondFactionList;
import static net.tv90.bfmccore.helper.FactionHelper.getCountry2;

public class ConquestArea {
    //占领点的范围
    public Area area;
    //占领点当前所属的阵营
    public String currentFaction = "NEUTRALIZED";
    public String originalFaction;
    //占领点代号 A,B,C,D,E
    public String index;
    //占领点中文名称
    public String name;
    //己方占领该点后，扣除对面每票所需时间(秒) 0为不扣除
    public int secondPerTicket = 1;
    //可协助占点的上限玩家数量
    public int maxPlayerMultiplier = 2;
    //占领点当前占领进度
    public double time = 0;
    //占领所需时间(秒)
    public double maxTime = 10;
    //是否允许占领
    public boolean canCapture;
    public boolean canCallCaptureEvent = false;
    //据点无人且处于Captured状态时自动恢复满占领状态时间间隔(每n秒恢复一格)
    public int autoRecoverInterval = 2;
    //占领点状态
    public ConquestAreaState state = ConquestAreaState.NEUTRALIZED;
    public ConquestAreaState originalState;
    //占领点玩家列表
    public Set<Player> firstFacInAreaPlayerList = new HashSet<>();
    public Set<Player> secondFacInAreaPlayerList = new HashSet<>();
    //GUI图标
    public ConquestAreaButton conquestAreaButton;
    //该占领点的A方出生点
    public List<Vector3i> firstFactionSpawn;
    //据点被抢夺时，该占领点的A方出生点
    public List<Vector3i> firstFactionSpawnWhenCapturing;
    //该占领点的B方出生点
    public List<Vector3i> secondFactionSpawn;
    //据点被抢夺时，该占领点的B方出生点
    public List<Vector3i> secondFactionSpawnWhenCapturing;

    public ConquestArea(Area area, String index, String name, boolean canCapture, List<Vector3i> firstFactionSpawn, List<Vector3i> firstFactionSpawnWhenCapturing, List<Vector3i> secondFactionSpawn, List<Vector3i> secondFactionSpawnWhenCapturing) {
        this.area = area;
        this.index = index;
        this.name = name;
        this.canCapture = canCapture;
        this.firstFactionSpawn = firstFactionSpawn;
        this.firstFactionSpawnWhenCapturing = firstFactionSpawnWhenCapturing;
        this.secondFactionSpawn = secondFactionSpawn;
        this.secondFactionSpawnWhenCapturing = secondFactionSpawnWhenCapturing;
    }

    public void initSource() {
        firstFacInAreaPlayerList.clear();
        secondFacInAreaPlayerList.clear();
        setCaptureState(originalFaction, originalState);
    }

    public void setCaptureState(String currentFaction, ConquestAreaState state) {
        this.currentFaction = currentFaction;
        this.state = state;
        if (state == ConquestAreaState.CAPTURED) this.time = maxTime;
        else this.time = 0;
        originalFaction = currentFaction;
        originalState = state;
    }

    public void setCaptureProperty(double maxTime, int secondPerTicket) {
        this.maxTime = maxTime;
        this.secondPerTicket = secondPerTicket;
    }

    public void setConquestAreaButtonPosition(int imagePosX, int imagePosY, int imageX, int imageY) {
        String url1 = "[local]BattleField/Menu_Null_" + index + ".png";
        String url2 = "[local]BattleField/Menu_Null_" + index + ".png";
        this.conquestAreaButton = new ConquestAreaButton(url1, url2, imagePosX, imagePosY, imageX, imageY, index);
    }

    public void teleportPlayerToConquestArea(Player p) {
        teleport(p);
    }

    public void teleport(Player p) {
        if (!checkIfCanDeploy(p)) {
            return;
        }
        String firstFactionName = GameManager.getInstance().currentGame.firstFactionName;
        String secondFactionName = GameManager.getInstance().currentGame.secondFactionName;
        String country = getCountry2(p);
        Vector3i vec;
        if (country.equals(firstFactionName)) {
            if (this.state == ConquestAreaState.CAPTURED) {
                vec = GameUtils.getExactSpawnPoint(p, firstFactionSpawn, EnumSpawnPolicy.RANDOM);
            } else
                vec = GameUtils.getExactSpawnPoint(p, firstFactionSpawnWhenCapturing, EnumSpawnPolicy.RANDOM);
            GameManager.getInstance().currentGame.teleportSinglePlayer2(p, vec);
        } else if (country.equals(secondFactionName)) {
            if (this.state == ConquestAreaState.CAPTURED) {
                vec = GameUtils.getExactSpawnPoint(p, secondFactionSpawn, EnumSpawnPolicy.RANDOM);
            } else
                vec = GameUtils.getExactSpawnPoint(p, secondFactionSpawnWhenCapturing, EnumSpawnPolicy.RANDOM);
            GameManager.getInstance().currentGame.teleportSinglePlayer2(p, vec);
        } else
            GameManager.getInstance().currentGame.teleportSinglePlayer2(p, GameManager.getInstance().currentGame.mainSpawnPoint);
        p.playSound(p.getLocation(), "custom.Deploy", 20.0F, 1.0F);
        GameManager.getInstance().currentGame.deploy(p);
    }

    public boolean checkIfCanDeploy(Player p) {
        if (Cooldown.isCool("Deploy", p)) {
            p.sendMessage("§a[队伍]部署冷却时间剩余" + Cooldown.getTime("Deploy", p) + "秒");
            return false;
        }
        String country = getCountry2(p);
        if (this.state == ConquestAreaState.NEUTRALIZED || !country.equals(currentFaction)) {
            GameModelViewHandler.getInstance().createInfoGui(p, "部署点已沦陷", GameModelViewHandler.getInstance()::createMainGUI);
            return false;
        }
        return true;
    }

    // 1/tps秒tick一次
    public void tick(int tps) {
        if (!canCapture || area == null) return;

        //计算区域内玩家集合
        firstFactionList.forEach(p -> {
            if (area.isInArea(new Vector3i((int) p.getLocation().getX(), (int) p.getLocation().getY(), (int) p.getLocation().getZ()))) {
                firstFactionAddPlayerToArea(p);
            } else {
                firstFacInAreaPlayerList.remove(p);
            }
            if (p.getHealth() <= 0) {
                firstFacInAreaPlayerList.remove(p);
            }
        });
        secondFactionList.forEach(p -> {
            if (area.isInArea(new Vector3i((int) p.getLocation().getX(), (int) p.getLocation().getY(), (int) p.getLocation().getZ()))) {
                secondFactionAddPlayerToArea(p);
            } else {
                secondFacInAreaPlayerList.remove(p);
            }
            if (p.getHealth() <= 0) {
                secondFacInAreaPlayerList.remove(p);
            }
        });

        //更新区域内玩家集合，并对玩家显示进度条
        firstFacInAreaPlayerList.forEach(p -> {
            if (!firstFactionList.contains(p)) firstFacInAreaPlayerList.remove(p);
            showProcessBar(p, currentFaction, time / maxTime);
        });
        secondFacInAreaPlayerList.forEach(p -> {
            if (!secondFactionList.contains(p)) secondFacInAreaPlayerList.remove(p);
            showProcessBar(p, currentFaction, time / maxTime);
        });

        //difference为两阵营人数的差值
        //该值大于0说明据点内A阵营人数多 小于0说明据点内B阵营人数多
        double difference = firstFacInAreaPlayerList.size() - secondFacInAreaPlayerList.size();
        if (difference != 0) {
            //当前占领点被A阵营占领
            if (currentFaction.equals(GameManager.getInstance().currentGame.firstFactionName)) {
                //B阵营人数多
                if (difference < 0) state = ConquestAreaState.CAPTURING;
                if (state != ConquestAreaState.CAPTURED) {
                    time += (Math.abs(difference) > maxPlayerMultiplier) ? Math.signum(difference) * maxPlayerMultiplier / (double) tps : difference / (double) tps;
                    state = ConquestAreaState.CAPTURING;
                }
            }

            //当前占领点被B阵营占领
            if (currentFaction.equals(GameManager.getInstance().currentGame.secondFactionName)) {
                //A阵营人数多
                if (difference > 0) state = ConquestAreaState.CAPTURING;
                if (state != ConquestAreaState.CAPTURED) {
                    time -= (Math.abs(difference) > maxPlayerMultiplier) ? Math.signum(difference) * maxPlayerMultiplier / (double) tps : difference / (double) tps;
                    state = ConquestAreaState.CAPTURING;
                }
            }

            //播放占领音效
            if (state != ConquestAreaState.CAPTURED) {
                if (difference > 0) {
                    firstFacInAreaPlayerList.forEach(player -> {
                        player.playSound(player.getLocation(), "custom.Capping_Flag", 200.0F, 1.0F);
                    });
                } else {
                    secondFacInAreaPlayerList.forEach(player -> {
                        player.playSound(player.getLocation(), "custom.Capping_Flag", 200.0F, 1.0F);
                    });
                }
            }

            //中立占领点
            if (currentFaction.equals("NEUTRALIZED")) {
                time += (Math.abs(difference) > maxPlayerMultiplier) ? maxPlayerMultiplier / (double) tps : Math.abs(difference) / (double) tps;
                //若 state 和 currentFaction 都为 NEUTRALIZED 触发中立事件
                if (state == ConquestAreaState.NEUTRALIZED) {
                    if (difference > 0) {
                        //System.out.println("FIRST FAC NEUTRALIZED");
                        Bukkit.getOnlinePlayers().forEach(player -> {
                            player.sendMessage("§a[队伍]" + index + "据点(" + name + ")已被中立化!");
                        });
                        firstFacInAreaPlayerList.forEach(p -> {
                            Bukkit.getServer().getPluginManager().callEvent(new FlagNeutralizedEvent(p, getCountry2(p), index, name));
                        });
                    } else {
                        //System.out.println("SECOND FAC NEUTRALIZED");
                        Bukkit.getOnlinePlayers().forEach(player -> {
                            player.sendMessage("§a[队伍]" + index + "据点(" + name + ")已被中立化!");
                        });
                        secondFacInAreaPlayerList.forEach(p -> {
                            Bukkit.getServer().getPluginManager().callEvent(new FlagNeutralizedEvent(p, getCountry2(p), index, name));
                        });
                    }
                    canCallCaptureEvent = true;
                }
                state = ConquestAreaState.CAPTURING;
            }

            //判定据点被占领
            if (state == ConquestAreaState.CAPTURING) {
                if (time >= maxTime) {
                    time = maxTime;
                    state = ConquestAreaState.CAPTURED;
                    if (difference > 0) {
                        //System.out.println("FIRST FAC CAPTURED");
                        currentFaction = GameManager.getInstance().currentGame.firstFactionName;

                        if (canCallCaptureEvent) {
                            Bukkit.getOnlinePlayers().forEach(player -> {
                                player.sendMessage("§a[队伍]" + index + "据点(" + name + ")已被" + currentFaction + "阵营占领!");
                            });
                            firstFactionList.forEach(player -> {
                                player.playSound(player.getLocation(), "game.CAPTURE_" + GameManager.getInstance().currentGame.firstFactionName, 200.0F, 1.0F);
                                player.playSound(player.getLocation(), "custom.Objective_Completed", 200.0F, 1.0F);
                                player.sendMessage("§a[队伍]我们已获得" + index + "据点(" + name + ")的控制权!");
                            });
                            secondFactionList.forEach(player -> {
                                player.playSound(player.getLocation(), "game.LOST_" + GameManager.getInstance().currentGame.secondFactionName, 200.0F, 1.0F);
                                player.sendMessage("§a[队伍]我们已失去" + index + "据点(" + name + ")的控制权!");
                            });
                            firstFacInAreaPlayerList.forEach(p -> {
                                Bukkit.getServer().getPluginManager().callEvent(new FlagCapturedEvent(p, getCountry2(p), index, name));
                            });
                        }
                    } else {
                        //System.out.println("SECOND FAC CAPTURED");
                        currentFaction = GameManager.getInstance().currentGame.secondFactionName;

                        if (canCallCaptureEvent) {
                            Bukkit.getOnlinePlayers().forEach(player -> {
                                player.sendMessage("§a[队伍]" + index + "据点(" + name + ")已被" + currentFaction + "阵营占领!");
                            });
                            firstFactionList.forEach(player -> {
                                player.playSound(player.getLocation(), "game.LOST_" + GameManager.getInstance().currentGame.firstFactionName, 200.0F, 1.0F);
                                player.sendMessage("§a[队伍]我们已失去" + index + "据点(" + name + ")的控制权!");
                            });
                            secondFactionList.forEach(player -> {
                                player.playSound(player.getLocation(), "game.CAPTURE_" + GameManager.getInstance().currentGame.secondFactionName, 200.0F, 1.0F);
                                player.playSound(player.getLocation(), "custom.Objective_Completed", 200.0F, 1.0F);
                                player.sendMessage("§a[队伍]我们已获得" + index + "据点(" + name + ")的控制权!");
                            });
                            secondFacInAreaPlayerList.forEach(p -> {
                                Bukkit.getServer().getPluginManager().callEvent(new FlagCapturedEvent(p, getCountry2(p), index, name));
                            });
                        }
                    }
                    canCallCaptureEvent = false;
                }
                //判定据点中立
                if (time <= 0) {
                    time = 0;
                    state = ConquestAreaState.NEUTRALIZED;
                    currentFaction = "NEUTRALIZED";
                }
            }
        }

        //据点自动恢复
        if (!currentFaction.equals("NEUTRALIZED")
                && state == ConquestAreaState.CAPTURING
                && firstFacInAreaPlayerList.isEmpty()
                && secondFacInAreaPlayerList.isEmpty()) {
            if (autoRecoverInterval > 0) {
                time += 1.0 / (double) autoRecoverInterval / (double) tps;
                if (time >= maxTime) {
                    time = maxTime;
                    state = ConquestAreaState.CAPTURED;
                }
            }
        }

        printInfo(difference);
    }

    public void firstFactionAddPlayerToArea(Player p) {
        if (p.getHealth() != 0) {
            firstFacInAreaPlayerList.add(p);
        }
    }

    public void secondFactionAddPlayerToArea(Player p) {
        if (p.getHealth() != 0) {
            secondFacInAreaPlayerList.add(p);
        }
    }

    public void showProcessBar(Player p, String currentFaction, double processPercent) {
        int windowWidth = VexViewAPI.getPlayerClientWindowWidth(p);
        int windowHeight = VexViewAPI.getPlayerClientWindowHeight(p);

        double barImageScale = 1.0 * windowWidth / 854;
        double barImageX = 64 * barImageScale;
        int barImageY = (int) (10 * barImageScale);
        int barPosX = -1;
        int barPosY = 300 * windowHeight / 445;
        String redOrBlue;
        if (currentFaction.equals(getCountry2(p)) || currentFaction.equals("NEUTRALIZED")) {
            redOrBlue = "blue";
        } else {
            redOrBlue = "red";
        }
        int lastTime = 1;

        VexImage flagBarEdge = new VexImage("[local]BattleField/bar_edge.png", barPosX, barPosY, (int) barImageX, barImageY);
        VexImage flagBar = new VexImage("[local]BattleField/bar_" + redOrBlue + ".png", barPosX, barPosY, (int) (barImageX * processPercent), barImageY);
        VexTextShow flagText = new VexTextShow("FlagText", 403 * windowWidth / 854, 290 * windowHeight / 445, 100, Collections.singletonList("FLAG STATUS"), lastTime, 1.0);
        VexViewAPI.sendHUD(p, new VexImageShow("Flag_Bar_Edge", flagBarEdge, lastTime));
        VexViewAPI.sendHUD(p, new VexImageShow("Flag_Bar", flagBar, lastTime));
        VexViewAPI.sendHUD(p, flagText);
    }

    public void printInfo(Object... obj) {
        //System.out.println(index + " " + currentFaction + " " + time + "/" + maxTime + " " + state + " canCall=" + canCallCaptureEvent);
    }

    public boolean isTeamCaptured(boolean firstOrSecond) {
        if (firstOrSecond) {
            return GameManager.getInstance().currentGame.firstFactionName.equals(currentFaction) && state == ConquestAreaState.CAPTURED;
        } else {
            return GameManager.getInstance().currentGame.secondFactionName.equals(currentFaction) && state == ConquestAreaState.CAPTURED;
        }
    }

    public boolean isOurTeamCaptured(Player p) {
        return FactionHelper.getCountry2(p).equals(currentFaction) && state == ConquestAreaState.CAPTURED;
    }

    @Override
    public String toString() {
        return "ConquestArea{" +
                "area=" + area +
                ", currentFaction='" + currentFaction + '\'' +
                ", originalFaction='" + originalFaction + '\'' +
                ", index='" + index + '\'' +
                ", name='" + name + '\'' +
                ", ticket=" + secondPerTicket +
                ", maxPlayerMultiplier=" + maxPlayerMultiplier +
                ", time=" + time +
                ", maxTime=" + maxTime +
                ", canCapture=" + canCapture +
                ", canCallCaptureEvent=" + canCallCaptureEvent +
                ", state=" + state +
                ", originalState=" + originalState +
                ", firstFacInAreaPlayerList=" + firstFacInAreaPlayerList +
                ", secondFacInAreaPlayerList=" + secondFacInAreaPlayerList +
                ", conquestAreaButton=" + conquestAreaButton +
                ", firstFactionSpawn=" + firstFactionSpawn +
                ", firstFactionSpawnWhenCapturing=" + firstFactionSpawnWhenCapturing +
                ", secondFactionSpawn=" + secondFactionSpawn +
                ", secondFactionSpawnWhenCapturing=" + secondFactionSpawnWhenCapturing +
                '}';
    }

    public void teleportPlayerToVehicleConquestArea(Player player, String type, String vehicle) {
    }

    public enum ConquestAreaState {
        NEUTRALIZED, CAPTURED, CAPTURING
    }
}
